package com.hb.bussiness.config;

import com.hb.common.constants.StringPoolConstant;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

import javax.annotation.PreDestroy;
import java.io.IOException;

/**
 * elasticsearch客户端配置
 *
 * @author hb
 * @date:2023/4/27 9:12
 * @date 2023/04/27
 */

public class ElasticsearchClientConfig {
    /**
     * 日志组件
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchClientConfig.class);

    /**
     * 建立连接超时时间
     */
    public static int CONNECT_TIMEOUT_MILLIS = 1000;
    /**
     * 数据传输过程中的超时时间
     */
    public static int SOCKET_TIMEOUT_MILLIS = 30000;
    /**
     * 从连接池获取连接的超时时间
     */
    public static int CONNECTION_REQUEST_TIMEOUT_MILLIS = 500;

    /**
     * 路由节点的最大连接数
     */
    public static int MAX_CONN_PER_ROUTE = 10;
    /**
     * client最大连接数量
     */
    public static int MAX_CONN_TOTAL = 30;

    /**
     * es 集群节点
     */
    @Value("${elasticsearch.clusterNodes:localhost:9200}")
    private String clusterNodes;


    /**
     * 账号
     */
    @Value("${elasticsearch.username}")
    private String username;

    /**
     * 账号
     */
    @Value("${elasticsearch.password}")
    private String password;

    /**
     * es rest client的bean对象
     */
    private RestHighLevelClient restHighLevelClient;

    public ElasticsearchClientConfig(RestHighLevelClient restHighLevelClient) {
        this.restHighLevelClient = restHighLevelClient;
    }

    /**
     * 加载es集群节点
     *
     * @return
     */
    private HttpHost[] loadHttpHost() {
        String[] clusterNodsArray = clusterNodes.split(StringPoolConstant.COMMA);
        HttpHost[] httpHosts = new HttpHost[clusterNodsArray.length];
        for (int i = 0; i < clusterNodsArray.length; i++) {
            String clusterNode = clusterNodsArray[i];
            String[] hostAndPort = clusterNode.split(StringPoolConstant.COLON);
            httpHosts[i] = new HttpHost(hostAndPort[0], Integer.parseInt(hostAndPort[1]));
        }


        return httpHosts;
    }

    @Bean
    public RestHighLevelClient restClient() {

        //需要用户名和密码的认证
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));

//       RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost("8.129.237.125", 9200, "http"))


        RestClientBuilder restClientBuilder = RestClient.builder(loadHttpHost()).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
            @Override
            public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
                return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
        });


//        setConnectTimeOutConfig(restClientBuilder);
//        setConnectConfig(restClientBuilder);
        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(restClientBuilder);
        return restHighLevelClient;
    }




    /**
     * 配置连接超时时间等参数
     *
     * @param restClientBuilder 创建restClient的构造器
     */
    private void setConnectTimeOutConfig(RestClientBuilder restClientBuilder) {
        restClientBuilder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(CONNECT_TIMEOUT_MILLIS);
            requestConfigBuilder.setSocketTimeout(SOCKET_TIMEOUT_MILLIS);
            requestConfigBuilder.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT_MILLIS);
            return requestConfigBuilder;
        });
    }

    /**
     * 使用异步httpclient时设置并发连接数
     *
     * @param restClientBuilder 创建restClient的构造器
     */
    private void setConnectConfig(RestClientBuilder restClientBuilder) {
        restClientBuilder.setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setMaxConnTotal(MAX_CONN_TOTAL);
            httpClientBuilder.setMaxConnPerRoute(MAX_CONN_PER_ROUTE);
            return httpClientBuilder;
        });
    }

    @PreDestroy
    public void close() {
        if (restHighLevelClient != null) {
            try {
                LOGGER.info("Closing the ES REST client");
                restHighLevelClient.close();
            } catch (IOException e) {
                LOGGER.error("Problem occurred when closing the ES REST client", e);
            }
        }
    }
}

